#![allow(unused_imports)]
use axum::{
    extract::{Form, Path, Query, Json, Multipart,DefaultBodyLimit},
    http:: {HeaderMap, HeaderValue,StatusCode},
    routing::{get_service,get,post,MethodRouter},
    response::{IntoResponse, Response,Redirect},
    body::{Body, Bytes},
    Router
};
use tower_sessions::Session;
use crate::controller::user_controller::UserRequest;
use crate::controller::user_controller::pick_user_picture;
use crate::controller::user_controller::store_user_picture;
use crate::domain::UserBean;
use crate::domain::UserQueryRequest;
use crate::domain::dto::LoginInput;
use crate::domain::dto::TokenPayload;
use crate::domain::error::Error;
use crate::serviceimpl::login_service::login_user as service_login_user;
use crate::serviceimpl::role_service::find_role_by_role_name as service_find_role_by_role_name;
use crate::serviceimpl::role_service::list_active_role_permissions_using_role_id as service_list_active_role_permissions_using_role_id;
use crate::serviceimpl::user_service::assign_roles_to_user as service_assign_roles_to_user;
use crate::serviceimpl::user_service::find_user_by_id as service_find_user_by_id;
use crate::serviceimpl::user_service::find_user_by_user_name as service_find_user_by_user_name;
use crate::serviceimpl::user_service::list_active_user_roles_using_user_id as service_list_active_user_roles_using_user_id;
use crate::serviceimpl::user_service::register_user as service_register_user;
use crate::utils::jwt_util;
use crate::utils::jwt_util::Claims;
use crate::utils::jwt_util::JWT_SECRET;
use jsonwebtoken::DecodingKey;
use jsonwebtoken::Validation;
use serde_json::{Value,Map};
use std::collections::HashMap;
use std::collections::HashSet;
use tower_http::{trace::TraceLayer};

pub fn login_controller() -> Router {
	Router::new()
	.route("/loginUser", post(login_user))
	.route("/logoutUser", get(logout_user))
	.route("/readMySession", get(read_my_session))
	.route("/registerUser", post(register_user))
	.route("/addUploadUserPhoto", post(add_upload_user_photo))
	.route("/canAdminAccess", get(can_admin_access))
	.route("/isLogin", get(is_login))
	.layer(TraceLayer::new_for_http())
}

pub async fn add_upload_user_photo(mut multipart:Multipart) ->String {
		while let Some(field) = multipart.next_field().await.unwrap() {
			let name = field.name().unwrap().to_string();
			if name == "files[]" {
				let content_type = field.content_type().unwrap().to_string();
				if content_type.starts_with("image/") {
					let data = field.bytes().await.unwrap();
					let data_str = base64::encode(data);
					store_user_picture("photo".to_string(),data_str.clone());

					let mut map = Map::new();
					map.insert("success".to_string(), Value::from(true));
					map.insert(
						"rows".to_string(),
						Value::from(data_str.clone()),
					);

					let resultjson = serde_json::to_string_pretty(&map).unwrap();
					return resultjson;
				}
			}
		}
		r#"{  "rows": null,  "success": true}"#.to_string()
}

pub async fn login_user(mut session:Session,Json(input):Json<LoginInput>) ->String {
	let user = service_login_user(input.user_name,input.password)
		.await;
	match user {
	Ok(user) => {
	let token = jwt_util::sign(user.id).unwrap();
		let _ = session.insert("token",token.clone()) .await ;
		let result = serde_json::to_string_pretty(&TokenPayload {
			success:true,
			token: token.clone()
		}).unwrap();
		result
	},
	Err(_) => {
		let mut map = Map::new();
			map.insert("success".to_string(), Value::from(false));
			map.insert(
				"error".to_string(),
				Value::from(Error::WrongCredentials.to_string()),
			);

		let result = serde_json::to_string_pretty(&map).unwrap();
		result
		}
	}
}

pub async fn read_my_session(Query(params):Query<HashMap<String, String>>,session:Session) ->String {
    let mut _token:String = "".to_string();
    if let Some(value) = params.get("token") {
        _token = value.clone();
    } else {
        if let Some(session_value) = session.get("token") .await.unwrap(){
            _token = session_value;
        }
    }
   	if _token.is_empty() {
      		return r#"{  "rows": null,  "success": false }"#.to_string();
   	}
	let claims:Claims = jsonwebtoken::decode(
		&_token,
		&DecodingKey::from_secret(JWT_SECRET.as_bytes()),
		&Validation::default(),
	)
	.map(|data| data.claims).unwrap();
	let user = service_find_user_by_id(claims.sub).await.unwrap();
	let roles = service_list_active_user_roles_using_user_id(user.id).await.unwrap();
	let mut privileges = HashSet::<String>::new();
	for role in &roles {
		let sub_privs = service_list_active_role_permissions_using_role_id(role.id).await.unwrap();
		for sub_priv in sub_privs {
			privileges.insert(sub_priv.perm_name);
		}
	}

	let mut role_names = HashSet::<String>::new();
	for role in roles {
		role_names.insert(role.role_name);
	}


	let user_json = serde_json::to_string_pretty(&user).unwrap();
	let roles_json = serde_json::to_string_pretty(&role_names).unwrap();
	let privileges_json = serde_json::to_string_pretty(&privileges).unwrap();

	let mut map = Map::new();
	map.insert("success".to_string(), Value::from(true));
	map.insert("user".to_string(),serde_json::from_str(&user_json).unwrap());
	map.insert("roles".to_string(),serde_json::from_str(&roles_json).unwrap());
	map.insert("perms".to_string(),serde_json::from_str(&privileges_json).unwrap());

	let resultjson = serde_json::to_string_pretty(&map).unwrap();
	return resultjson;
}

pub async fn register_user(Json(user_request):Json<UserRequest>) ->String {
	let id = user_request.id.unwrap_or_default();
	let user_name = user_request.user_name.unwrap_or_default();
	let active = user_request.active.unwrap_or_default();
	let first_name = user_request.first_name.unwrap_or_default();
	let last_name = user_request.last_name.unwrap_or_default();
	let email = user_request.email.unwrap_or_default();
	let isadmin = user_request.isadmin.unwrap_or_default();
	let password = user_request.password.unwrap_or_default();
	let gender = user_request.gender.unwrap_or_default();
	let salt = user_request.salt.unwrap_or_default();
	let login_failure = user_request.login_failure.unwrap_or_default();
	let address = user_request.address.unwrap_or_default();
	let phone = user_request.phone.unwrap_or_default();
	let description = user_request.description.unwrap_or_default();
	let my_photo = pick_user_picture("photo".to_string());

	let user = UserBean{
	id : id,
	user_name : user_name,
	active : active,
	first_name : first_name,
	last_name : last_name,
	email : email,
	isadmin : isadmin,
	password : password,
	gender : gender,
	salt : salt,
	login_failure : login_failure,
	address : address,
	phone : phone,
	description : description,
	photo : my_photo,
	};

	let user0 = service_find_user_by_user_name(user.clone().user_name).await;

	match user0 {
		Ok(user0) => {
			if user0.id > 0 {
				return r#"{  "rows": null,  "success": false, "error":"用户已存在"}"#.to_string();
			}
		},
		Err(_) => {
		}
	}
	let _result = service_register_user(user.clone()).await;
	match _result {
		Err(_) => {
			r#"{  "rows": null,  "success": true}"#.to_string()
		},
		Ok(_result) => {
			// let role = service_find_role_by_role_name("user".to_string()).await.unwrap();
			// let user = service_find_user_by_user_name(user.clone().user_name).await.unwrap();
			// let _ = service_assign_roles_to_user(user.id,vec![role.id]).await;
			let mut map = Map::new();
			map.insert("success".to_string(), Value::from(true));
			map.insert(
				"rows".to_string(),
				Value::from(""),
			);

			let resultjson = serde_json::to_string_pretty(&map).unwrap();
			return resultjson;
		}
	}
}

pub async fn logout_user(mut session:Session) ->String {
	let _ = session.remove::<String>("token").await;
	let mut map = Map::new();
	map.insert("success".to_string(), Value::from(true));
	map.insert(
		"rows".to_string(),
		Value::from(""),
	);

	let resultjson = serde_json::to_string_pretty(&map).unwrap();
	return resultjson;
}

pub async fn can_admin_access(Query(params):Query<HashMap<String, String>>,session:Session) ->String {
   	let mut _token:String = "".to_string();
    if let Some(value) = params.get("token") {
        _token = value.clone();
    } else {
        if let Some(session_value) = session.get("token") .await.unwrap(){
            _token = session_value;
        }
    }
   	if _token.is_empty() {
        return r#"{  "rows": null,  "success": false }"#.to_string();
   	}
	let claims:Claims = jsonwebtoken::decode(
		&_token,
		&DecodingKey::from_secret(JWT_SECRET.as_bytes()),
		&Validation::default(),
	)
	.map(|data| data.claims).unwrap();
	let user = service_find_user_by_id(claims.sub).await.unwrap();
	let roles = service_list_active_user_roles_using_user_id(user.id).await.unwrap();
    let mut canAccess = false;
	for role in roles {
		if role.role_name == "admin"{
		  canAccess = true;
		}
	}
	let mut map = Map::new();
	map.insert("success".to_string(), Value::from(true));
	map.insert("canAccess".to_string(),Value::from(canAccess));
	let resultjson = serde_json::to_string_pretty(&map).unwrap();
	return resultjson;
}

pub async fn is_login(Query(params):Query<HashMap<String, String>>,session:Session) ->String {
   	let mut _token:String = "".to_string();
    if let Some(value) = params.get("token") {
        _token = value.clone();
    } else {
        if let Some(session_value) = session.get("token").await.unwrap() {
            _token = session_value;
        }
    }
   	if _token.is_empty() {
        return r#"{  "isLogin": false,  "success": false }"#.to_string();
   	}
	let claims:Claims = jsonwebtoken::decode(
		&_token,
		&DecodingKey::from_secret(JWT_SECRET.as_bytes()),
		&Validation::default(),
	)
	.map(|data| data.claims).unwrap();
	let user = service_find_user_by_id(claims.sub).await.unwrap();
    let mut isLogin = false;
    if user.id > 0 {
        isLogin = true;
    }
	let mut map = Map::new();
	map.insert("success".to_string(), Value::from(true));
	map.insert("isLogin".to_string(),Value::from(isLogin));
	let resultjson = serde_json::to_string_pretty(&map).unwrap();
	return resultjson;
}
